<?php
/**
*  @package :  class.tool
*  @classID :  Upload.class.php
*  @author  :  邝达峰
*  @date    :  2014-03-17
*  上传文件类
*/

class Upload
{
	public $upload_dir;#上传路径
	public $max_size;#上传大小
	public $default_max_size=1024;#上传大小默认最大值1M
	public $upload_name;#上传名字
	public $error;#上传错误
	private $img_mw = null;#图片宽度
	private $img_mh = null;#图片高度
	public $arrConfig = array();
	public $BUILD_IMG = NULL;#需要生成图片的配置
	public $image_dir;

	/**
	*  构造函数
	*  @param $upload_dir,$max_size,$build(上传路径不存在,是否自动建立)
	*  @return NULL
	*  @access public
	*/
	public function __construct($upload_dir,$max_size=1024,$build=true)
	{

		#获取文件配置
		$this->arrConfig = Config::get('file');
		if(!empty($upload_dir)){
			if(is_array($this->arrConfig['CHANNEL_UPLOADIMG_CONFIG'][$upload_dir])){ //在配置里面
				$upload_dir_name = $this->arrConfig['CHANNEL_UPLOADIMG_CONFIG'][$upload_dir]['alias'];
				$max_size = $this->arrConfig['CHANNEL_UPLOADIMG_CONFIG'][$upload_dir]['max_file_size'];
			}else{ //不在配置里面
				if(strpos($upload_dir,'/')){   //兼容旧的传入参数
					$upload_dir_old = $upload_dir;
				}else{    //读默认配置
					$upload_dir_name = $this->arrConfig['CHANNEL_UPLOADIMG_CONFIG']['default']['alias'];
					$max_size = $this->arrConfig['CHANNEL_UPLOADIMG_CONFIG']['default']['max_file_size'];
				}
			}
		}else{
			$upload_dir_name = $this->arrConfig['CHANNEL_UPLOADIMG_CONFIG']['default']['alias'];
			$max_size = $this->arrConfig['CHANNEL_UPLOADIMG_CONFIG']['default']['max_file_size'];
		}
		if($upload_dir_old){
			$upload_dir = $upload_dir_old;
		}else{
			$upload_dir = "uploads/".$upload_dir_name."/".date("m")."/".date("d")."/";
		}

		#设置上传路径
		$this->upload_dir = $this->setUploadDir($upload_dir,$build);
		#设置上传大小
		$this->max_size = $max_size?$max_size: $this->default_max_size;
		#设置图片路径
		$this->image_dir = '/'.$upload_dir;


	}


	/**
	 * 创建唯一实例
	 */
	public static function &getInstance($upload_dir='')
	{
		static $instance = null;
		if(!is_object($instance))
		{
			$c = __CLASS__;
			$instance = new $c($upload_dir);
		}
		return $instance;
	}

	/**
	*  上传路径检查
	*  @param $upload_dir,$flag
	*  @return $array
	*  @access public
	*/
	public function setUploadDir($uplad_dir,$build=true)
	{
		$all_dir = WEB_ROOT.$uplad_dir;

		if(!is_dir($all_dir))
		{
			if($build)
			{
				preg_match_all('/([^\/]+)/', $uplad_dir, $matches);
				$check_path = WEB_ROOT;
				foreach($matches[1] as $v)
				{
					$check_path .= DIRECTORY_SEPARATOR.$v;
					if(!file_exists($check_path))
					{
						mkdir($check_path);
					}
				}
				$all_dir = $check_path.DIRECTORY_SEPARATOR;
			}
			else
			{
				$this->error = $GLOBALS['lang']['FILE_ULOAD_FTP_ERROR'];
			}
		}
		return $all_dir;
	}

	/**
	*  获得上传文件信息
	*  @param $file
	*  @return $array
	*  @access public
	*/
	public function getFileInfo($file)
	{
		return pathinfo($file);
	}

	/**
	*  获得上传文件扩展
	*  @param $file
	*  @return $extension
	*  @access public
	*/
	public function getFileExtension($file)
	{
		return pathinfo($file,PATHINFO_EXTENSION);
	}

	/**
	*  获得新上传文件名称函数
	*  /s_x1_100.0222112837149563_349_313_10383.jpg
	*  存储beandb的编号 地理位置编号  存储时间 其他默认
	*  @param $name_old
	*  @return $name_new
	*  @access public
	*/
	public function getNewFileName($file)
	{
		$extension = $this->getFileExtension($file['name']);
		list($w,$h)=images_size($file['tmp_name']);
		$filesize=$file['size'];
		$server = $this->arrConfig['IMG_SERVER'];
		$name   = $server['UPLOAD_SERVER_IDX'].'_'.$server['UPLOAD_LOC'].'.'.time();
		return $name."_".$w."_".$h."_".$filesize.".".$extension;
	}

	/**
	*  上传文件属性检查函数
	*  @param $name,$size,$type,
	*  @return NULL
	*  @access public
	*/
	public function fileCheck($upFile,$type)
	{
		#判断类型;
		if(is_array($upFile["name"])){
			$len = count($upFile["name"]);
			for($k = 0;$k<$len;$k++)
			{
				$v["name"] = $upFile['name'][$k];
				$v["type"] = $upFile['type'][$k];
				$v["tmp_name"] = $upFile['tmp_name'][$k];
				$v["error"] = $upFile['error'][$k];
				$v["size"] = $upFile['size'][$k];
				$this->fileCheck($v,$type);
			}
		}else{
			$extension = strtolower($this->getFileExtension($upFile["name"]));
			switch($type)
			{
				case 'image':
					if (!in_array($extension,array('gif', 'png','jpg','jpeg')))
					{
						$this->error .= '图片不是JPG或GIF格式或PNG格式.\n';
						return false;
					}
					if(!$this->imageCheck($upFile["tmp_name"]))
					{
						$this->error .= '图片规格太大.\n';
						return false;
					}
					break;
				case 'music':
					if ($extension != "mp3"  && $extension != "wma")
					{
						$this->error .= $this->extension."不是MP3格式.\n";
						return false;
					}
					break;
				case 'flash':
					if ($extension != "swf" )
					{
						$this->error .= 'FLASH文件格式不是swf.\n';
						return false;
					}
					break;
				case 'movie':
					#检查文件大小
					if ($extension != "avi" && $extension != "swf" )
					{
						$this->error .= '电影文件格式不是wma或mp3.\n';
						return false;
					}
					break;
				case 'mv':
					if ($extension != "flv" )
					{
						$this->error .= $extension."不是MV格式.\n";
						return false;
					}
					break;
				case 'file':
					#检查文件格式
					if (!in_array($extension,array('txt','doc','xml','rar','zip','xls')))#允许上传xls文件
					{
						$this->error .= '网站不支持此文件格式上传.\n';
						return false;
					}
					break;
				default:
					$this->error .= '文件类型参数错误';
					return false;
					break;
			}
		}
		#检查文件大小
		if ( $upFile['size'] > $this->max_size*1024){
			if($this->max_size <= 1000)
			{
				$this->error .='文件大小不能超过'.$this->max_size. 'KB'."\n";
			}else
			{
				$this->error .='文件大小不能超过1M'."\n";
			}
			return false;
		}
		return true;
	}

	/**
	*  上传图片宽高检查函数
	*  @param $file_upload
	*  @return Null
	*  @access public
	*/
	public function imageCheck($uploadFile)
	{
		if (!$this->img_mw || !$this->img_mh){
			return true;
		}else{
			list($width,$height) = images_size($uploadFile);
			if ($width > $this->img_mw or $height > $this->img_mh)
			{
				$this->error = '图片分辨率超过限定: 宽'.$this->img_mw .' * 高'.$this->img_mh.' px.\n';
				unlink($uploadFile);
				return false;
			}
			return true;
		}
	}

	/**
	* 上传文件并获得新文件名
	*  @param：$file 上传文件
	*  @param：$uploadName 指定上传后的文件名
	*  @param：$type 上传类型
	*  @param：$suffix 下标
	*  @param：$flag(如上传文件存在的处理方法)
	*  @param：$batch 是否批量上传
	*  @return 路径
	*  @access public
	**/
	public function uploadFile($file,$uploadName='',$suffix=0,$type='image',$flag=false,$batch=false){
		#判断是否数组
		if(is_array($file) && $batch){
			$upFile = $file;
		}else{
			if(is_array($_FILES[$file]['name'])){
				$upFile["name"] = $_FILES[$file]['name'][$suffix];
				$upFile["type"] = $_FILES[$file]['type'][$suffix];
				$upFile["tmp_name"] = $_FILES[$file]['tmp_name'][$suffix];
				$upFile["error"] = $_FILES[$file]['error'][$suffix];
				$upFile["size"] = $_FILES[$file]['size'][$suffix];
			}else{
				$upFile = $_FILES[$file];
			}
		}

		if($upFile["error"] !== 0){
			$this->error = '上传失败:获取不到源文件!';
			return false;
		}
		#检测上传文件
		if(!$this ->fileCheck($upFile,$type)){
			$this ->error = $upFile["name"].'上传失败,'.$this ->error."\n";
			return false;
		}
		#检测是否同名
		if (!$uploadName){
			$this->upload_name = $this->getNewFileName($upFile);
			if (file_exists($this->upload_dir.$this->upload_name) )
			{
				$this->error = $upFile['name'].'上传失败,同名文件已存在;请重新上传!\n';
				return false;
			}
		}else{
			$this->upload_name = $uploadName;
			if (is_file($this->upload_dir.$this->upload_name)){
				if ($flag){
					unlink($this-> upload_dir.$this->upload_name);
				}else{
					$this->error = $this->upload_name.'文件已存在;如需更新请以更新模式上传!\n';
				}
			}
		}
		#保存在redis


		if ($this->arrConfig['IMG_SERVER']['UPLOAD_IMGS_TYPE']){
			#redis配置
			$confg = $this->arrConfig['IMG_SERVER']['REDIS']['WRITE']['0'];
			#邝达峰 获取redis缓存真实路径 2014-01-18
			$strImagePath = $this->image_dir.$this->upload_name;
			$strImageContent = file_get_contents($upFile['tmp_name']);
			if(REDIS_IMAGE_SEP){
				$strImageContent = $strImagePath.REDIS_IMAGE_SEP.file_get_contents($upFile['tmp_name']);
			}
			try {
				if(Upload_redis::instance($confg)->set(md5($strImagePath),$strImageContent)){
					#直接保存推出
					return $this->image_dir.$this->upload_name;#保存一天
				}
			}
			catch (Exception  $e){
				return false;
			}

		}
		#复制文件到指定目录
		$is_up_img = true;
		if(is_array($this->BUILD_IMG))
		{
			$this->BUILD_IMG['batch'] = $batch;
			#生成缩略图
			$is_up_img = $this->build_img($upFile['tmp_name'],$this->upload_dir.$this->upload_name,$file);
		}
		if($is_up_img)
		{
			if(!move_uploaded_file($upFile['tmp_name'],$this->upload_dir.$this->upload_name))
			{
				if(!rename($upFile['tmp_name'],$this->upload_dir.$this->upload_name))
				{
					$this->error = $upFile['name'].'上传失败,请检测上传目录是否存在或拥有操作权限!\n';
					return false;
				}
				@chmod($this->upload_dir.$this->upload_name, 0755);
			}
		}
		return $this->image_dir.$this->upload_name;
	}

	/**
	*  上传文件处理
	*  @param $type 上传类型
	*  @param $isToSave 是否返回保存
	*  @return path
	*  @access public
	*/
	public function upFiles($type='image',$isToSave = true){


		//检查上传图片是否正确
		if(!$this->checkImageError()){
			return false;
		}
		foreach($_FILES as $k=>$v){
			if(is_array($v['name'])){
				for($i=0;$i<count($v['name']);$i++){
					if($v['error'][$i]===0 && ($newImg = $this->uploadFile($k,'',$i,$type))){
						$up_file[$k][$i] = $newImg;
					}
				}
			}elseif($v['error']===0  && ($newImg = $this->uploadFile($k,'',$i,$type))){
				$up_file[$k] = $newImg;
			}
		}
		if($isToSave && is_array($up_file)){
			$_REQUEST = array_merge($_REQUEST, array_filter($up_file));
			if(is_array($up_file)){
				$arrImagePath = array_values($up_file);
				if(is_array($arrImagePath)){
					$imagePath = $arrImagePath[0];
				}
				return $imagePath?$imagePath:null;
			}
		}else{
			if($up_file){
				return $up_file;
			}else{
				return	$_REQUEST['img-upload-erro']=$this->error;
			}
		}

	}

	/**
	 * 检查图片错误
	 * 0——没有错误发生，文件上传成功。 
       1——上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。 
       2——上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。 
       3——文件只有部分被上传。 
       4——没有文件被上传。  
	 */
	private function checkImageError(){
		$arrError  = array('0' => '文件上传成功',
		'1' => '上传的文件超过了upload_max_filesize选项限制的值',
		'2' => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
		'3' => '文件只有部分被上传',
		'4' => '没有文件被上传',
		'other' => '未知错误');

		foreach($_FILES as $k=>$v){
			if(is_array($v['name'])){
				for($i=0;$i<count($v['name']);$i++){
					if($v['error'][$i]!==0){
						if (array_key_exists($v['error'][$i], $arrError)) {
							$this->error=$arrError[$v['error'][$i]];
						}else{
							$this->error = $arrError['other'];
						}
						return false;
					}
				}
			}elseif($v['error']!==0){
				if (array_key_exists($v['error'], $arrError)) {
					$this->error=$arrError[$v['error']];
				}else{
					$this->error = $arrError['other'];
				}
				return false;
			}
		}
		return true;
	}

	/**
	 * 删除上传文件 
	 * @param $file要删除的文件路径
	 * @param $type:0 只删除这个文件 1删除相关缩略图
	 */
	public function del_file($file,$type = 0){
		if(is_string($file)){
			if($tmp_arr = unserialize($file)) $file = $tmp_arr;
		}
		if(is_array($file)){
			foreach($file as $v){
				if($tmp_arr = unserialize($v)) $v = $tmp_arr;
				if(is_array($v)) $this->del_file($v,$type);
                
				/*
				if($this->arrConfig['IMG_SERVER']['UPLOAD_IMGS_TYPE']){

					#设置redis日志
					Upload_redis::instance($this->arrConfig['IMG_SERVER']['REDISLOG']['0'])->set(md5($v).'_',$v);
					if($this->arrConfig['IMG_SERVER']['UPLOAD_IMGS_TYPE']== 1) {
						continue;
					}
				}
				*/
				if(!empty($v)){
					@unlink('.'.$v);
					if($type == 1){
						$str_del = substr(WEB_ROOT,0,-1).preg_replace("/([^\/]+)$/","*_$1",$v);
						exec("rm $str_del");
					}
				}
			}
		}elseif(!empty($file)){
			if($this->arrConfig['IMG_SERVER']['UPLOAD_IMGS_TYPE']){
				if($this->arrConfig['IMG_SERVER']['UPLOAD_IMGS_TYPE'] == 1) {
					return;
				}
			}
			@unlink('.'.$file);
			if($type == 1){
				$str_del = substr(WEB_ROOT,0,-1).preg_replace("/([^\/]+)$/","*_$1",$file);
				exec("rm $str_del");
			}
		}
	}



	/**
	 * 删除图片
	 * @param  $tbl 数据表名称
	 * @param  $where 查询条件
	 * @param  $colImg 图片字段名称
	 * @return null
	 */
	public function delImg($tbl,$where='',$colImg='')
	{
		if(empty($colImg) && isset($_FILES))
		{
			$colImg = '';
			foreach($_FILES as $k=>$v)
			{
				if($v["error"] === 0) $colImg[]= $k;
				elseif(is_array($v["error"]) && array_sum($v["error"]) == 0)
				{
					$colImg[]= $k;
				}
			}
			if(is_array($colImg)) $colImg = implode(',',$colImg);
		}
		elseif(is_array($colImg))
		{
			$colImg = implode(',',$colImg);
		}
		if(empty($colImg))
		{
			return false;
		}
		$tmpArr = DB::select("select $colImg from $tbl where $where ");

		if(is_array($tmpArr))
		{
			foreach($tmpArr as $v)
			{
				$this->del_file($v,1);
			}
		}
	}





	/**
	 * 批量上传图片文件
	 * @param $arrFiles 需要处理的文件数组
	 * @param $imgPath 图片保存路径
	 * @param $buildImg 是否生成缩略图
	 * @return path 路径数组
	 */
	public  function batchUploadImageFiles($arrFiles=array(),$imgPath='',$max_size = '1024',$buildImg=false){
		if(is_array($arrFiles) && count($arrFiles) > 0 && !empty($imgPath)){
			$filePath = array();
			#创建图片对象
			foreach($arrFiles as $k=>$v){
				$oImage = BaseAction::image($imgPath,$max_size);
				#是否生成缩略图
				if($buildImg){
					$oImage->BUILD_IMG[$k]['s'][] = array(100,100);
					$oImage->BUILD_IMG[$k]['s'][] = array(225,140);
					$oImage->BUILD_IMG[$k]['n'][] = 's_';			//缩略图前缀名
					$oImage->BUILD_IMG[$k]['n'][] = 'm_';
					$oImage->BUILD_IMG[$k]['b'][] = false;
				}
				#上传图片
				if($v['error']===0){
					$newImg = $oImage->uploadFile($v,'',$k,'image',false,true);
					if($newImg){
						$filePath[$k] = $newImg;
					}
				}
			}
			#图片路径保存
			if(is_array($filePath) && count($filePath) >0){
				$_REQUEST = array_merge($_REQUEST, array_filter($filePath));
				$imagePath = array_values($filePath);
				return $imagePath?$imagePath:null;
			}
		}
	}

	/**
	 * $img :图片路径 ...../s_x1_1.1348014868_31_31_2608.gif
	 * $conf :服务器配置文件
	 * */
	public  static function  get_beansdb($img,$conf){
		$info = pathinfo($img);
		$exd  = explode('.',$info['basename']);
		if($exd['2']){
			#新图片
			$cons  = explode('_',$exd['0']);
			$cons2 = explode('_',$exd['1']);
			$res['type']  = '1';
			$res['time']  = $cons2['0'];
			if($cons['2']){
				#有缩略图
				$res['loc']   = $cons['2'];
				$res['pre']   = $cons['1'];
				$res['server'][]= $conf['CONFG'][$cons['1']];
			}else{
				$res['loc']   = $cons['1'];
				$res['pre']   = $cons['0'];
				$res['server'][]= $conf['CONFG'][$cons['0']];
			}
		}else{
			#老图片
			$res['pre']   = 'default';
			$res['loc']   = '';
			$res['type']  = '0';
			$res['server']= $conf['CONFG']['default'];
		}
		return $res;
	}

	/**
	 * 删除提交图片列表
	 * @param  $images
	 * @param  $key
	 * @return array
	 */
	public function getPostImgList($images,$key='')
	{
		$arr_post = array();
		$arr_post_n = array();
		foreach($images as $k=>$v)
		{
			$k = empty($key)?$k:$key;
			if(is_array($v)){
				$reArr = $this->getPostImgList($v,$k);
				$arr_post = array_merge($arr_post,$reArr[0]);
				$arr_post_n = array_merge($arr_post_n,$reArr[1]);
			}else{
				if($type != 'del' && isset($this->BUILD_IMG)) {
					#查找相缩略图
					if(empty($this->BUILD_IMG[$k]['n']) && $this->BUILD_IMG[$k]['t'] != 2)
					{
						$arr_post_n[] = "img_n".urlencode('[]')."=".urlencode('s_');
					}
					elseif($this->BUILD_IMG[$k]['n'])
					{
						if(is_array($this->BUILD_IMG[$k]['n']))
						{
							$arr_post_n[] = "img_n".urlencode('[]')."=".urlencode(implode('|',$this->BUILD_IMG[$k]['n']));
						}
						else
						{
							$arr_post_n[] = "img_n".urlencode('[]')."=".urlencode($this->BUILD_IMG[$k]['n']);
						}
					}
				}
				$arr_post[] = "img".urlencode('[]')."=".urlencode($v);
			}
		}
		return array($arr_post,$arr_post_n);
	}

	/**
	 * 通过post提交图片
	 */
	public function post($images,$type='add'){}

	/**
     *生成缩略图
     *全局变量：$BUILD_IMG[col]['s'] = array(11,11); 缩略图宽度*高度 (col为列名)
     *			$BUILD_IMG[col]['n'] = 's_';		 缩略图前缀名
     *			$BUILD_IMG[col]['r'] = true;		 是否生成水印 默认为true
     *			$BUILD_IMG[col]['b'] = true;		 是否填充背景色 默认为true
     *			$BUILD_IMG[col]['t'] = 1			 0为生成缩略图,1为不生成缩略图,2为只生成缩略图不保留原图 默认为0
     */
	public function build_img($tmpFile,$newName,$key){
		if(is_array($this->BUILD_IMG)){
			if(is_array($this->BUILD_IMG[$key])){
				$build = $this->BUILD_IMG[$key];
			}else{
				return true;
			}
			if($build['t'] == 1){
				return true;
			}
			if(empty($build['n']) && $build['t'] != 2){
				$build['n'] = 's_';
			}elseif(!isset($build['n'])){
				$build['n'] = '';
			}
			if(!isset($build['r']))
			{
				$build['r'] = true;
			}
			if(!isset($build['b']))
			{
				$build['b'] = true;
			}
			require 'Image.class.php';
			preg_match("/^(.+\/)([^\/]+)$/",$newName, $matches);
			$path = $matches[1];
			$newName = $matches[2];
			if(is_array($build['s']))
			{
				foreach($build['s'] as $k => $v)
				{
					$s = $key>0?$key:'';
					if(is_array($build['n']))
					$n = empty($build['n'][$k])?$n.$s.'_':$build['n'][$k];
					else
					$n = $build['n'];
					Image::getReduceImage($tmpFile,$v[0],$v[1],$path.$n.$newName);
					if($build['r'][$k]) Image::getWaterMarkImage($path.$n.$newName,Image::mWaterImage);
					if($build['b'][$k]) Image::imgFill($path.$n.$newName,$v[0],$v[1]);
					@chmod($path.$n.$newName, 0755);
				}
			}
			else
			{
				Image::getReduceImage($tmpFile,$build['s'][0],$build['s'][1],$path.$build['n'].$value);
				if($build['r']) Image::getWaterMarkImage($path.$build['n'].$value,Image::mWaterImage);
				if($build['b']) Image::imgFill($path.$n.$newName,$build['s'][0],$build['s'][1]);
				@ chmod($path.$build['n'].$value, 0755);
			}
			if($build['t'] == 2)
			{
				return false;
			}
		}
		return true;
	}


	/**
	* 文件流的方式上传文件并获得新文件名
	*  @param：$strImageContent,文件流,输入的参数必须是文件流,$extension扩展名.png
	*  @return string 路径
	*  @access public
	*  @author 张伟杰
	*  @date 20140815
	**/
	public function uploadFilecontent($strImageContent,$extension=false){

		//得到名称
		$this->upload_name = $this->getNewFileStreamName($strImageContent,$extension);

		if (file_exists($this->upload_dir.$this->upload_name) )
		{
			$this->error = $this->upload_name.'上传失败,同名文件已存在;请重新上传!\n';
			return false;
		}

		#保存在redis
		if ($this->arrConfig['IMG_SERVER']['UPLOAD_IMGS_TYPE']){
			#redis配置
			$confg = $this->arrConfig['IMG_SERVER']['REDIS']['WRITE']['0'];
			//生成路径
			$strImagePath = $this->image_dir.$this->upload_name;
			if(REDIS_IMAGE_SEP){
				$strImageContent = $strImagePath.REDIS_IMAGE_SEP.$strImageContent;
			}
			if(Upload_redis::instance($confg)->set(md5($strImagePath),$strImageContent)){
				return $this->image_dir.$this->upload_name;//保存一天
			}
		}

		return $this->image_dir.$this->upload_name;
	}


	/**
	*  获得新上传文件流名称函数
	*  @param $fileabc 文件流
	*  @param $extension 扩展名
	*  @return file path
	*  @access public
	*/
	public function getNewFileStreamName($fileabc,$extension=false)
	{
		if($fileabc&&$extension)
		{
			#获取文件大小
			$gfile = imagecreatefromstring($fileabc);
			$w=imagesx($gfile);
			$h=imagesy($gfile);
			$filesize=strlen($fileabc);
			#生成图片
			$server = $this->arrConfig['IMG_SERVER'];
			$name   = $server['UPLOAD_SERVER_IDX'].'_'.$server['UPLOAD_LOC'].'.'.time();
			return $name."_".$w."_".$h."_".$filesize.".".$extension;
		}
	}


}
?>